﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Hosting;
using StackExchange.Redis;
using Activity.Redis;
using Activity.Redis.Helper;
using Activity.Helper;

// ReSharper disable once CheckNamespace
namespace com.km.Cache
{
    /// <summary>
    /// 使用Redis保存缓存
    /// </summary>
    public static class RedisCache
    {

        private static RedisClient _rcClient;
        private const string Prefix = "km:c:";
        static RedisClient Client => _rcClient ?? (_rcClient = new RedisClient(ConfigurationHelper.Get<int>("redis-cache-index", 8)));

        private static string GetKey(string key)
        {
            return $"{Prefix}{(ConfigurationHelper.Get("isDebug", false) ? "t" : "d")}:{key}";
        }

        /// <summary>
        /// 添加一个项目到Redis
        /// 如果key已经存在则覆盖
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">基本类型（int，float。。。）</param>
        /// <param name="minutes"></param>
        public static RedisValue Add(string key, RedisValue value, int minutes)
        {
            Client.SetString(GetKey(key), value, minutes);
            return value;
        }
        /// <summary>
        /// 添加一个项目到Redis
        /// 如果key已经存在则覆盖
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">基本类型（int，float。。。）</param>
        /// <param name="minutes"></param>
        public static void AddString(string key, string value, int minutes)
        {
            Client.SetString(GetKey(key), value, minutes);
        }
        /// <summary>
        /// 添加一个项目到Redis
        /// 如果key已经存在则覆盖
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">基本类型（int，float。。。）</param>
        /// <param name="ts"></param>
        /// <returns></returns>
        public static RedisValue Add(string key, RedisValue value, TimeSpan ts)
        {
            Client.SetString(GetKey(key), value, ts);
            return value;
        }
        /// <summary>
        /// 添加一个项目到Redis
        /// 如果key已经存在则覆盖
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="ts"></param>
        /// <returns></returns>
        public static string AddString(string key, string value, TimeSpan ts)
        {
            Client.SetString(GetKey(key), value, ts);
            return value;
        }
        /// <summary>
        /// 添加一个项目到Redis
        /// 如果key已经存在则覆盖
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="ts"></param>
        /// <returns></returns>
        public static int AddInt(string key, int value, TimeSpan ts)
        {
            Client.SetString(GetKey(key), value, ts);
            return value;
        }
        /// <summary>
        /// 添加一个项目到Redis 如果key已经存在则覆盖
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="minutes"></param>
        /// <returns></returns>
        public static int AddInt(string key, int value, int minutes)
        {
            Client.SetString(GetKey(key), value, minutes);
            return value;
        }
        /// <summary>
        /// 添加一个项目到Redis
        /// 如果key已经存在则覆盖
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">必须可序列化</param>
        /// <param name="minutes"></param>
        public static T AddObject<T>(string key, T value, int minutes)
        {
            Client.GetDatabase().SetString(GetKey(key), value, TimeSpan.FromMinutes(minutes));
            return value;
        }
        /// <summary>
        /// 永久存储数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">基本类型</param>
        public static RedisValue Max(string key, RedisValue value)
        {
            Client.SetString(GetKey(key), value);
            return value;
        }
        /// <summary>
        /// 永久存储数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">可以序列号的对象</param>
        public static object Max(string key, object value)
        {
            Client.GetDatabase().SetString(GetKey(key), value);
            return value;
        }
        /// <summary>
        /// 永久存储数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">可以序列号的对象</param>
        public static long MaxLong(string key, long value)
        {
            Client.AddLong(GetKey(key), value);
            return value;
        }
        /// <summary>
        /// 永久存储数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">可以序列号的对象</param>
        public static void MaxString(string key, string value)
        {
            Client.AddString(GetKey(key), value);
        }
        /// <summary>
		/// 永久存储数据
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value">可以序列号的对象</param>
		public static void MinString(string key, string value, int min)
        {
            Client.AddString(GetKey(key), value, min);
        }
        /// <summary>
        /// 重置超时时间
        /// </summary>
        /// <param name="key"></param>
        /// <param name="minutes"></param>
        public static void Expire(string key, int minutes)
        {
            Client.Expire(GetKey(key), minutes);
        }

        #region SET
        /// <summary>
        /// 永久存储IEnumerable&lt;T&gt;数据（集合SET）
        /// 添加一个列表到SET
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void MaxSetList<T>(string key, IEnumerable<T> value) where T : class, new()
        {
            foreach (var item in value)
            {
                Client.GetDatabase().SetSet(GetKey(key), item);
            }
        }
        /// <summary>
        /// 永久存储T数据（集合SET）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void MaxSetListAdd<T>(string key, T value) where T : class, new()
        {
            Client.GetDatabase().SetSet(GetKey(key), value);
        }
        /// <summary>
        /// 永久存储T数据（集合SET）
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void MaxSetListAdd(string key, string value)
        {
            Client.AddValueToSet(GetKey(key), value);
        }
        /// <summary>
        /// 永久存储IEnumerable&lt;RedisValue&gt;数据（集合SET）
        /// 添加一个列表到SET
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void MaxSetList(string key, IEnumerable<RedisValue> value)
        {
            foreach (var item in value)
            {
                Client.AddValueToSet(GetKey(key), item);
            }
        }
        /// <summary>
        /// 永久存储Object数据（集合SET）
        /// 把传入的value添加到SET（key指定的）里面
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static object MaxSetAdd(string key, object value)
        {
            Client.GetDatabase().SetSet(GetKey(key), value);
            return value;
        }
        /// <summary>
        /// 永久存储Object数据（集合SET）
        /// 把传入的value添加到SET（key指定的）里面
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static object MaxSetAddInt(string key, int value)
        {
            Client.AddValueToSet(GetKey(key), value);
            return value;
        }
        /// <summary>
        /// 永久存储RedisValue数据（集合SET）
        /// 把传入的value添加到SET（key指定的）里面
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static RedisValue MaxSetAdd(string key, RedisValue value)
        {
            Client.AddValueToSet(GetKey(key), value);
            return value;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string MaxSetAddString(string key, string value)
        {
            Client.AddValueToSet(GetKey(key), value);
            return value;
        }
        #endregion

        #region LIST

        /// <summary>
        /// 从LIST中读取 字符串列表
        /// </summary>
        /// <param name="pKey"></param>
        /// <param name="skip"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public static IEnumerable<string> GetListList(string pKey, int skip, int limit)
        {
            if (!Exists(pKey))
            {
                return new string[] { };
            }
            var qs = Client.GetList(GetKey(pKey), skip, skip + limit).ToList();
            return qs.Any()
                ? qs.Select(s => s.ToString())
                : new string[] { };

        }
        /// <summary>
        /// 从LIST中读取数据并移除
        /// </summary>
        /// <param name="pKey"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static IEnumerable<string> ListLeftPop(string pKey, int count)
        {
            if (!Exists(pKey))
            {
                return new string[] { };
            }
            var db = Client.GetDatabase();
            var theKey = GetKey(pKey);
            var length = db.ListLength(theKey);
            var reslut = new List<string>();
            for (var i = 0; i < count && i < length; i++)
            {
                reslut.Add(db.ListLeftPop(theKey));
            }

            return reslut;
        }

        /// <summary>
        /// 添加到列表，尾部（右边）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T MaxListAdd<T>(string key, T value) where T : class, new()
        {
            Client.GetDatabase().ListRightPush(GetKey(key), Serialize(value));
            return value;
        }
        /// <summary>
        /// 添加到列表，尾部（右边）
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string MaxListAdd(string key, string value)
        {
            Client.GetDatabase().ListRightPush(GetKey(key), value);
            return value;
        }
        /// <summary>
        /// 把列表顶部（左边）的值取出
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T ListPop<T>(string key) where T : class, new()
        {
            var value = Client.GetDatabase().ListLeftPop(GetKey(key));
            return Deserialize<T>(value);
        }
        /// <summary>
        /// 把列表顶部（左边）的值取出
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string ListPopString(string key)
        {
            var value = Client.GetDatabase().ListLeftPop(GetKey(key));
            return value;
        }
        /// <summary>
        ///  返回一个LIST的“长度”
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static long CountList(string key)
        {
            return Client.GetListLength(GetKey(key));
        }

        #endregion

        #region Hash
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="value"></param>
        public static void AddHash(string hashKey, string field, RedisValue value)
        {
            Client.HashSet(GetKey(hashKey), field, value);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="value"></param>
        public static void HashAdd(string hashKey, int field, object value)
        {
            var db = Client.GetDatabase();
            db.HashSet(GetKey(hashKey), field, (RedisValue)value);
        }
        public static void HashAddIntString(string hashKey, int field, string value)
        {
            var db = Client.GetDatabase();
            db.HashSet(GetKey(hashKey), field, value);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="value"></param>
        public static void HashAdd(string hashKey, long field, object value)
        {
            var db = Client.GetDatabase();
            db.HashSet(GetKey(hashKey), field, (RedisValue)value);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="value"></param>
        public static void HashAdd(string hashKey, string field, object value)
        {
            var db = Client.GetDatabase();
            db.HashSet(GetKey(hashKey), field, (RedisValue)value);
        }
        public static void HashAdd(string hashKey, string field, string value)
        {
            var db = Client.GetDatabase();
            db.HashSet(GetKey(hashKey), field, value);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="value"></param>
        /// <param name="minutes"></param>
        public static void AddHash(string hashKey, string field, RedisValue value, int minutes)
        {
            Client.HashSet(GetKey(hashKey), field, value);
            Expire(hashKey, minutes);
        }
        public static void RemoveHash(string hashKey, int field)
        {
            Client.GetDatabase().HashDelete(GetKey(hashKey), field);
        }
        public static void RemoveHash(string hashKey, string field)
        {
            Client.GetDatabase().HashDelete(GetKey(hashKey), field);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static RedisValue GetHash(string hashKey, string field, RedisValue dv)
        {
            return Client.HashGet(GetKey(hashKey), field, dv);
        }
        public static IDictionary<string, string> GetAllHashStr(string hashKey)
        {
            if (!Exists(hashKey))
                return null;
            var list = Client.GetDatabase().HashGetAll(GetKey(hashKey));
            var dict = new Dictionary<string, string>();
            foreach (var item in list)
            {
                dict.Add((string)item.Name, (string)item.Value);
            }
            return dict;
        }
        public static IDictionary<int, string> GetAllHashIntStr(string hashKey)
        {
            if (!Exists(hashKey))
                return null;
            var list = Client.GetDatabase().HashGetAll(GetKey(hashKey));
            var dict = new Dictionary<int, string>();
            foreach (var item in list)
            {
                dict.Add((int)item.Name, (string)item.Value);
            }
            return dict;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static string GetHashString(string hashKey, string field, string dv)
        {
            return Client.HashGet(GetKey(hashKey), field, dv);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="field"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static string GetHashString(string hashKey, int field, string dv)
        {
            return Client.HashGet(GetKey(hashKey), field, dv);
        }

        #endregion

        /// <summary>
        /// 判断是否存在key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Exists(string key)
        {
            return Client.KeyExists(GetKey(key));
        }
        /// <summary>
        /// 判断hash里面key是否存在
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool HashExists(string hashKey, string key)
        {
            if (!Exists(hashKey))
            {
                return false;
            }
            return Client.GetDatabase().HashExists(GetKey(hashKey), key);
        }
        /// <summary>
        /// 判断hash里面key是否存在
        /// </summary>
        /// <param name="hashKey"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool HashExists(string hashKey, int key)
        {
            if (!Exists(hashKey))
            {
                return false;
            }
            return Client.GetDatabase().HashExists(GetKey(hashKey), key);
        }
        /// <summary>
        /// 判断 item 是否存在SET（key）中
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool SetExists(string key, RedisValue value)
        {
            return Exists(key) && Client.IsItemExists(GetKey(key), value);
        }
        /// <summary>
        /// 判断 item 是否存在SET（key）中
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool SetExistsInt(string key, int value)
        {
            return Exists(key) && Client.IsItemExists(GetKey(key), value);
        }
        /// <summary>
		/// 判断 item 是否存在SET（key）中
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public static bool SetExistsString(string key, string value)
        {
            return Exists(key) && Client.IsItemExists(GetKey(key), value);
        }
        /// <summary>
        /// 从Redis缓存中读取数据（基本类型）
        /// key不存在则返回dv
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static RedisValue Get(string key, RedisValue dv)
        {
            return Client.GetString(GetKey(key), dv);
        }
        /// <summary>
        /// 从Redis缓存中读取数据（基本类型）
        /// key不存在则返回nil
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static RedisValue Get(string key)
        {
            return Client.GetString(GetKey(key));
        }
        /// <summary>
        /// 从Redis缓存中获取JSON字符串并转换为数据对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T GetAndDecodeJson<T>(string key)
        {
            //if (!Exists(key))
            //    return default(T);
            var str = (string)Client.GetString(key);
            return str.FromJson<T>();
        }
        /// <summary>
        /// 从Redis缓存中获取字符串
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetString(string key)
        {
            return Client.GetString(GetKey(key));
        }
        /// <summary>
        /// 从Redis缓存中获取字符串
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static string GetString(string key, string dv)
        {
            return Client.GetString(GetKey(key), dv);
        }

        /// <summary>
        /// 从Redis缓存中获取字符串
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static string Get(string key, string dv)
        {
            return Client.GetString(GetKey(key), dv);
        }

        /// <summary>
        /// 从Redis缓存中获取 Int
        /// </summary>
        /// <param name="key"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static int GetInt(string key, int dv)
        {
            return Client.GetInt(GetKey(key), dv);
        }
        /// <summary>
        /// 从Redis缓存中读取数据（对象--可系列化）
        /// key不存在则返回dv
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="dv"></param>
        /// <returns></returns>
        public static T Get<T>(string key, T dv) where T : class, new()
        {
            return Exists(key)
                ? Deserialize<T>(Client.GetString(GetKey(key), new byte[] { }))
                : dv;
        }
        /// <summary>
        /// 从Redis缓存中读取一组数据（对象--可系列化）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pattern"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static IEnumerable<T> GetList<T>(string pattern, int count) where T : class, new()
        {
            if (Count(pattern) < 1) return new List<T>();
            var keys = Client.GetKeys(GetKey(pattern), count);
            var result = new List<T>();
            foreach (var key in keys)
            {
                result.Add(Get<T>(key));
            }
            return result;
        }

        /// <summary>
        /// 从Redis缓存中读取数据（对象）
        /// 如果key不存在则返回null
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T Get<T>(string key) where T : class, new()
        {
            return Exists(key)
                ? Deserialize<T>(Client.GetString(GetKey(key), new byte[] { }))
                : null;
        }
        /// <summary>
        /// 从Redis缓存中读取数据（SET）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static List<T> GetSet<T>(string key) where T : class, new()
        {
            if (!Exists(key))
            {
                return null;
            }
            var count = Client.GetSetLength(GetKey(key));
            var result = new List<T>();
            if (count < 1000)
            {
                var values = Client.GetDatabase().SetMembers(GetKey(key));
                foreach (var item in values)
                {
                    result.Add(Deserialize<T>(item));
                }
            }
            else
            {
                var loop = true;
                var ps = 1000;
                var off = 0;
                var cursor = 0L;
                while (loop)
                {
                    var list = Client.GetDatabase().SetScan(GetKey(key),
                        cursor: cursor,
                        pageSize: ps,
                        pageOffset: off
                        );
                    foreach (var item in list)
                    {
                        result.Add(Deserialize<T>(item));
                    }
                    var ic = list as IScanningCursor;
                    loop = ic != null && ic.Cursor > 0;
                    if (ic != null)
                    {
                        ps = ic.PageSize;
                        off = ic.PageOffset;
                        cursor = ic.Cursor;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 从Redis缓存中读取数据（SET）
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static IList<int> GetSetInt(string key)
        {
            if (!Exists(key))
            {
                return null;
            }
            var count = Client.GetSetLength(GetKey(key));
            var result = new List<int>();
            if (count < 1000)
            {
                var values = Client.GetDatabase().SetMembers(GetKey(key));
                foreach (var item in values)
                {
                    result.Add((int)item);
                }
            }
            else
            {
                var loop = true;
                var ps = 1000;
                var off = 0;
                var cursor = 0L;
                while (loop)
                {
                    var list = Client.GetDatabase().SetScan(GetKey(key),
                        cursor: cursor,
                        pageSize: ps,
                        pageOffset: off
                        );
                    foreach (var item in list)
                    {
                        result.Add((int)item);
                    }
                    var ic = list as IScanningCursor;
                    loop = ic != null && ic.Cursor > 0;
                    if (ic != null)
                    {
                        ps = ic.PageSize;
                        off = ic.PageOffset;
                        cursor = ic.Cursor;
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// 从Redis缓存中读取数据（SET）
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static IList<string> GetSetString(string key)
        {
            if (!Exists(key))
            {
                return null;
            }
            var count = Client.GetSetLength(GetKey(key));
            var result = new List<string>();
            if (count < 1000)
            {
                var values = Client.GetDatabase().SetMembers(GetKey(key));
                foreach (var item in values)
                {
                    result.Add((string)item);
                }
            }
            else
            {
                var loop = true;
                var ps = 1000;
                var off = 0;
                var cursor = 0L;
                while (loop)
                {
                    var list = Client.GetDatabase().SetScan(GetKey(key),
                        cursor: cursor,
                        pageSize: ps,
                        pageOffset: off
                        );
                    foreach (var item in list)
                    {
                        result.Add((string)item);
                    }
                    var ic = list as IScanningCursor;
                    loop = ic != null && ic.Cursor > 0;
                    if (ic != null)
                    {
                        ps = ic.PageSize;
                        off = ic.PageOffset;
                        cursor = ic.Cursor;
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// 从Redis缓存中移除数据
        /// </summary>
        /// <param name="key"></param>
        public static void Remove(string key)
        {
            Client.RemoveKey(GetKey(key));
        }
        /// <summary>
        /// 从Redis缓存中移除数据（模糊搜索）
        /// </summary>
        /// <param name="pattern"></param>
	    public static void RemoveByPattern(string pattern)
        {
            Client.RemoveKeysByPattern(pattern);
        }

        /// <summary>
        /// 从Redis缓存中移除RedisValue数据(SET)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void RemoveSet(string key, RedisValue value)
        {
            if (!Exists(key))
            {
                return;
            }
            Client.GetDatabase().SetRemove(GetKey(key), value);
        }
        /// <summary>
        /// 从Redis缓存中移除Object数据(SET)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void RemoveSet(string key, object value)
        {
            if (!Exists(key))
            {
                return;
            }
            Client.GetDatabase().SetRemove(GetKey(key), Serialize(value));
        }
        /// <summary>
        /// 从Redis缓存中移除Object数据(SET)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void RemoveSetInt(string key, int value)
        {
            if (!Exists(key))
            {
                return;
            }
            Client.RemoveValueFromSet(GetKey(key), value);
        }
        /// <summary>
        /// 从Redis缓存中移除Object数据(SET)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void RemoveSetString(string key, string value)
        {
            if (!Exists(key))
            {
                return;
            }
            Client.RemoveValueFromSet(GetKey(key), value);
        }
        /// <summary>
        /// 统计关键字（Key）的数量
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public static long Count(string pattern)
        {
            return Client.Count(GetKey(pattern));
        }

        /// <summary>
        /// 搜索关键字
        /// </summary>
        /// <param name="pattern"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public static IEnumerable<string> GetKeys(string pattern, int page, int limit)
        {
            return Client.GetKeys(GetKey(pattern), page, limit).Select(s => s.ToString()).ToList();
        }
        public static IEnumerable<string> GetKeys(string pattern, int limit)
        {
            return Client.GetKeys(GetKey(pattern), limit).Select(s => s.ToString()).ToList();
        }

        /// <summary>
        /// 获取指定集合（SET）的值得数量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static long SetCount(string key)
        {
            return Client.GetSetLength(GetKey(key));
        }
        /// <summary>
        /// 插入原子
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
	    public static long MaxIncrement(string key)
        {
            var db = Client.GetDatabase();
            key = GetKey(key);
            var r = db.StringIncrement(key);
            return r;
        }
        public static long MinusIncrement(string key, int pValue)
        {
            var db = Client.GetDatabase();
            key = GetKey(key);
            var r = db.StringDecrement(key, pValue);
            return r;
        }

        #region Helper
        /// <summary>
        /// 设置String
        /// </summary>
        /// <param name="dataBase"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeSpan"></param>
        public static void SetString(this IDatabase dataBase, string key, object value, TimeSpan? timeSpan = null)
        {
            if (value == null) throw new ArgumentNullException("key");
            dataBase.StringSet(key, Serialize(value), timeSpan);
        }
        /// <summary>
        /// 设置SET
        /// </summary>
        /// <param name="dataBase"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetSet(this IDatabase dataBase, string key, object value)
        {
            if (value == null) throw new ArgumentNullException("key");
            dataBase.SetAdd(key, Serialize(value));
        }
        static T Deserialize<T>(byte[] stream) where T : class, new()
        {
            if (stream == null)
            {
                return null;
            }
            var binaryFormatter = new BinaryFormatter();
            using (var memoryStream = new MemoryStream(stream))
            {
                var result = (T)binaryFormatter.Deserialize(memoryStream);
                return result;
            }
        }
        static byte[] Serialize(object o)
        {
            if (o == null)
            {
                return null;
            }
            var binaryFormatter = new BinaryFormatter();
            using (var memoryStream = new MemoryStream())
            {
                binaryFormatter.Serialize(memoryStream, o);
                var objectDataAsStream = memoryStream.ToArray();
                return objectDataAsStream;
            }
        }
        #endregion
    }
}
